/*
 * SimpleUnit.java
 *
 * Copyright 2008 the Desert Labs Project (http://desertlabs.us)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package us.desertlabs.physics;

/**
 * This class serves as the base class for all datatypes representing simple
 * unit values that generally do not contain multi-dimensional information.
 * Examples of this are <CODE>Mass</CODE>, <CODE>Energy</CODE>, and <CODE>Power</CODE>.
 *
 * @author Brandon Franklin
 */
public abstract class SimpleUnit extends Number {

    /** The amount of the unit represented */
    final private Number amount;

    /**
     * Creates a new instance of <CODE>SimpleUnit</CODE> representing the
     * supplied amount of whatever the unit measures.
     *
     * @param amount the amount of whatever this unit measures
     * @throws IllegalArgumentException if the supplied amount is null
     */
    public SimpleUnit( final Number amount ) {
        if( amount == null ) {
            throw new IllegalArgumentException( "Value cannot be null." );
        }
        this.amount = amount;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public byte byteValue() {
        return amount.byteValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double doubleValue() {
        return amount.doubleValue();
    }

    /**
     * Returns true if the value of this <CODE>SimpleUnit</CODE> is equal to
     * the object supplied, false otherwise. There are only two types of objects
     * that can be provided as parameters: <CODE>SimpleUnit</CODE>s and
     * <CODE>Number</CODE>s. Any other class type will cause an exception to
     * be thrown.
     *
     * @param obj the object to check for equality to this one
     * @return true if the value of this <CODE>SimpleUnit</CODE> is equal to
     *         the object supplied, false otherwise
     * @throws IllegalArgumentException if the parameter is of the wrong
     *         datatype or is invalid for any reason
     */
    @Override
    public boolean equals( final Object obj ) {

        // Validate the object
        if( obj == null ) {
            throw new IllegalArgumentException( "Equality cannot be determined with a null object." );
        }

        // Evaluate object based on datatype
        if( obj instanceof SimpleUnit ) {
            return ((SimpleUnit)obj).numberValue().equals( amount );

        } else if( obj instanceof Number ) {
            return ((Number)obj).equals( amount );

        } else {
            throw new IllegalArgumentException( "Equality to a SimpleUnit can only be determined for SimpleUnits and Numbers." );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public float floatValue() {
        return amount.floatValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return amount.hashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int intValue() {
        return amount.intValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long longValue() {
        return amount.longValue();
    }

    /**
     * Returns the value of this object as a <CODE>Number</CODE> object.
     * Specifically, the actual <CODE>Number</CODE> object being used
     * internally to store the value of the <CODE>SimpleUnit</CODE> will be
     * returned.
     *
     * @return the value of this object as a <CODE>Number</CODE> object
     */
    public Number numberValue() {
        return amount;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public short shortValue() {
        return amount.shortValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return amount.toString();
    }
}
